/** global varb */
const MAX_LOOP_DEEPTH = 10;
const storage = {};
const listener = {}; // key: [listeners]
let deepth = 0; // callback deepth
export const app = {
  k: {
    SELECT_TILE_INDEX: "selectTileIndex",
    SELECT_TILE_DATA: "selectTileData",
    SELECT_TILE_WIDTH: "selectTileWidth",
    SELECT_TILE_HEIGHT: "selectTileHeight",
    CURRENT_TILE_MAP_SELECTOR: "currentTileMapSelector",
    EVENT_SELECT_TILE_CHANGE: "eventSelectTileChange", // any
    EVENT_SELECT_TILE_DATA_CHANGE: "eventSelectTileDataChange", // any
    EVENT_CURRENT_TILE_MAP_SELECTOR_CHANGE: "eventCurrentTileMapSelectorChange", // number of effect tile index, or less than zero means all
  },
  // global storage
  set(name, value){
    storage[name] = value;
    // call the listener
    if (name in listener){
      let listeners = listener[name];
      listeners.forEach(cb => {
        if (typeof(cb) == "function"){
          deepth += 1;
          try{
            // do not loop too deep....
            if (deepth <= MAX_LOOP_DEEPTH){
              cb(name, value);
            }else{
              console.error("you may have some circled listeners... we stopped it for you.");
            }
          }catch(err){
            console.error(err);
          }finally{
            deepth -= 1;
          }
        }
      });
    }
  },
  get(name, fallback=undefined){
    let val = storage[name];
    if (val === undefined){
      return fallback;
    }else{
      return storage[name];
    }
  },
  /**
   * register callback when set [name]`s value
   * @param {string} name key
   * @param {(name?:string, value?:any)=>void} cb callback
   */
  register(name, cb){
    if (!(name in listener)){
      listener[name] = [];
    }
    listener[name].push(cb);
  },
  unregister(name, cb){
    if (name in listener){
      let listeners = listener[name];
      let index = listeners.indexOf(cb);
      if (index >= 0){
        listeners.splice(index,1);
      }
    }
  }
};
window["app"] = app;
window["storage"] = storage;